! RUN: %python %S/test_folding.py %s %flang_fc1
! Test numeric model inquiry intrinsics

module m

  integer, parameter :: &
    bs1 = bit_size(0_1), &
    bs2 = bit_size(0_2), &
    bs4 = bit_size(0_4), &
    bs8 = bit_size(0_8), &
    bs16 = bit_size(0_16)
  logical, parameter :: test_bit_size_1 = bs1 == 8
  logical, parameter :: test_bit_size_2 = bs2 == 16
  logical, parameter :: test_bit_size_4 = bs4 == 32
  logical, parameter :: test_bit_size_8 = bs8 == 64
  logical, parameter :: test_bit_size_16 = bs16 == 128

  real(2), parameter :: &
    eps2 = epsilon(0._2), zeps2 = real(z'1400', kind=2), deps2 = 9.765625e-4_2
  real(3), parameter :: &
    eps3 = epsilon(0._3), zeps3 = real(z'3c00', kind=3), deps3 = 7.8135e-3_3
  real(4), parameter :: &
    eps4 = epsilon(0._4), zeps4 = real(z'34000000', kind=4), &
    deps4 = 1.1920928955078125e-07_4
  real(8), parameter :: &
    eps8 = epsilon(0._8), zeps8 = real(z'3cb0000000000000', kind=8), &
    deps8 = 2.2204460492503130808472633361816406250e-16_8
  real(10), parameter :: &
    eps10 = epsilon(0._10), zeps10 = real(z'3fc08000000000000000', kind=10), &
    deps10 = 1.08420217248550443400745280086994171142578125e-19_10
  real(16), parameter :: &
    eps16 = epsilon(0._16), &
    zeps16 = real(z'3f8f0000000000000000000000000000', kind=16), &
    deps16 = 1.9259299443872358530559779425849273185381016482153881952399387955665588378906250e-34_16
  logical, parameter :: test_eps2 = eps2 == zeps2 .and. eps2 == deps2
  logical, parameter :: test_eps3 = eps3 == zeps3 .and. eps3 == deps3
  logical, parameter :: test_eps4 = eps4 == zeps4 .and. eps4 == deps4
  logical, parameter :: test_eps8 = eps8 == zeps8 .and. eps8 == deps8
  logical, parameter :: test_eps10 = eps10 == zeps10 .and. eps10 == deps10
  logical, parameter :: test_eps16 = eps16 == zeps16 .and. eps16 == deps16

  integer(1), parameter :: &
    ihuge1 = huge(0_1), zihuge1 = int(z'7f', kind=1), dihuge1 = 127_1
  integer(2), parameter :: &
    ihuge2 = huge(0_2), zihuge2 = int(z'7fff', kind=2), dihuge2 = 32767_2
  integer(4), parameter :: &
    ihuge4 = huge(0_4), zihuge4 = int(z'7fffffff', kind=4), &
    dihuge4 = 2147483647_4
  integer(8), parameter :: &
    ihuge8 = huge(0_8), zihuge8 = int(z'7fffffffffffffff', kind=8), &
    dihuge8 = 9223372036854775807_8
  integer(16), parameter :: &
    ihuge16 = huge(0_16), &
    zihuge16 = int(z'7fffffffffffffffffffffffffffffff', kind=16), &
    dihuge16 = 170141183460469231731687303715884105727_16
  logical, parameter :: test_ihuge1 = ihuge1 == zihuge1 .and. ihuge1 == dihuge1
  logical, parameter :: test_ihuge2 = ihuge2 == zihuge2 .and. ihuge2 == dihuge2
  logical, parameter :: test_ihuge4 = ihuge4 == zihuge4 .and. ihuge4 == dihuge4
  logical, parameter :: test_ihuge8 = ihuge8 == zihuge8 .and. ihuge8 == dihuge8
  logical, parameter :: test_ihuge16 = ihuge16 == zihuge16 .and. ihuge16 == dihuge16

  real(2), parameter :: &
    ahuge2 = huge(0._2), zahuge2 = real(z'7bff', kind=2), dahuge2 = 6.5504e4_2
  real(3), parameter :: &
    ahuge3 = huge(0._3), zahuge3 = real(z'7f7f', kind=3), &
    dahuge3 = 3.3895313892515354759047080037148786688e38_3
  real(4), parameter :: &
    ahuge4 = huge(0._4), zahuge4 = real(z'7f7fffff', kind=4), &
    dahuge4 = 3.4028234663852885981170418348451692544e38_4
  real(8), parameter :: &
    ahuge8 = huge(0._8), zahuge8 = real(z'7fefffffffffffff', kind=8), &
    dahuge8 = 1.7976931348623157081452742373170435679807056752584499659891747680315726078002853876058955863276687817&
               &1540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868&
               &5084551339423045832369032229481658085593321233482747978262041447231687381771809192998812504040261841&
               &24858368e308_8
  real(10), parameter :: &
    ahuge10 = huge(0._10), zahuge10 = real(z'7ffeffffffffffffffff', kind=10), &
    dahuge10 = 1.1897314953572317650212638530309702051690633222946242004403237338917370055229707226164102903365288828&
                &5354569780749557731442744315367028843419812557385374367867359320070697326320191591828296152436552951&
                &0646791086614311790632169778838896134786560600399148753433211454911160088679845154866512852340149773&
                &0376000091254793939662231513836224178385427439178381387178058894875405751682263476592355769748051137&
                &2564902088485522249479139937758502601177354918009979622602685950855888360815984690023564513234659447&
                &6384939859276456284579661772930407806609229102715046085388087959327781622986827547830768080040150694&
                &9423034117289577771003357140105597752421240573470073862516601108283791196230084692772009651535002084&
                &7447079244384854591288672300061908512647211195136146752763351956292759795725027800298079590419313960&
                &3021470997035276467445530922022679656280991498232083329641241038509239184734786121921697210543484287&
                &0483534081130425730022164213489173471742348007148807510020643905172342476560047217680964861079949434&
                &1570347632064355862420744350442438056613601760883747816538902780957697597728686007148702828795556714&
                &1404632615832623602762896316173978484254486860609948270867968048078702511858930838546584223040908805&
                &9962945945862019037660484467909260022254105307759010657606713472001258464069570302571389609837579989&
                &2695455305236856075868317922311363951946885088077187210470520395758748001314313144425494391994017575&
                &3169339392366881856189129931729104252921236835159922322050998001677102784035360140829296398115122877&
                &7681357060457893435354516965395612540488464471697868932116710872290880827783505182288576460622187397&
                &0285165508372099234948333443522898475123275372663606621390228126470623407535207172405866507951821730&
                &3463782631353393706774901950197841690441824738063162828586857741432581165364040218402724913393320949&
                &2194984224427304270198730445366203502623869578046820036014472919971230955300572061418669748528468561&
                &8651483271597448120312194675168637934309618961510733006555242148519520176285859509105183947250286387&
                &1632494167613804996319791441870254302706758495192008837915169401581740046711477877201459644461175204&
                &0594535047647218079757611117208462736392796003396704700376133745095531841500737964126050479232516613&
                &5484129188421134082301547330475406707281876350361733290800595189632520707167390454777712968226520622&
                &5651439919376804400292380903112437912614776255964694221981375146967079446870358004392507659451618379&
                &8118593920495440361149153107822510726914869798092409467721427270124043771874092167566136349389004512&
                &3235166814608932240069799317601780533819184998193300841098599393876029260139091141452600372028487213&
                &2411955424282101831204216104467404621635336900583664606591156298764745525068145003932941404131495400&
                &6776029510059622530228230036314738246810596484424413248645731374375950964161680480241293518762046681&
                &3563687753281467553879887177183651289394719533506188500326760735438867336800207438784965701457609034&
                &9857571243045102038730494854256702479339322809110526041538528994849203991091946129912491633289917998&
                &0943803378795220931314669461497059396641523759492858909604899161219449899863848370224866722491489246&
                &7841020618336462741696957630763248023558797524525373703543388296086275342774001633343405508353704850&
                &7374544819754722228975281083020898682633020285259923084168054539687911418297629988964576482765287504&
                &5628549242651652177507995162596692291149777889623566709566271384820181913483216879958636526376209782&
                &8507009933729439678463987902491451422274252700636394232799848397673998715441855420156224415492665301&
                &4515504685489258620276085761837129763358761215382565129633538141663949516556000264159186554850057052&
                &6114319529199188079545223946496276356301785808966922264062353828985358675959906470083856871238103295&
                &9192649484625076899225841930548076362021508902214922052806984201835084058693849381549890944546197789&
                &3029113576516775406232278298314033473276603952231603422824717528181818844304880921321933550869873395&
                &8612760736708666523755556758031714901084773200964243187800700087973460329062789435537435644488519071&
                &9161645514115576193939969076741515640282654366402676009508752394550734155613586793306603174472092444&
                &6513532366647649735400851967040771103640538150073486891798364049570606189535005089840913826869535090&
                &0667833244725787121966044152849248400418509328119089636341757398971665960007594878006191640948543387&
                &5852065711654107226099628815012314437794400874930194474433078438899570184271000480830501217712356062&
                &2895076269042856800047718893158089358515593863176652948089031267747029662545110861548958395087796755&
                &4641379448959605279752098748138397625785921057562844017593493241621483395653501891968113890918437957&
                &3470326940634289008780584694035245347939808067427323629788710086717580253156130235606487870925986528&
                &8416350972529537091114317204887747405539054009425375424119317944175137064689643861517718849867010341&
                &5325423859110896247108853858086888377772586485641459342621210866475884892600317623459607695088491496&
                &6244415660441955208681198977024e4932_10
  real(16), parameter :: &
    ahuge16 = huge(0._16), zahuge16 = real(z'7ffeffffffffffffffffffffffffffff', kind=16), &
    dahuge16 = 1.1897314953572317650857593266280070161964690526416940455296988842121635797553123923249740128484620735&
                &2590203356474912685975526543357380446267269875194526149085346195872502126284586579940540449357468156&
                &6096686172574953791792292256220777095858112702436475442537092608935138247345677279593806773692330094&
                &6157461197257841728898925219399207576542048645656733564522472781522888677006389355954564966995114417&
                &5290960687851325094831139688610052683309212868397475219226638679188087369434307734815556410166997113&
                &8512786874753496996549221727686770196551512812712488289469952298031867469924683981576664562667786719&
                &0614996396303416570983054252372208766646300878087672561828032202122199248523759030495209113959109189&
                &2120527349676858811903011159301878936803923201167140417584510885470696521560577711351625740481881769&
                &5075025715299705916714352103671782759119316034498392169720631800164034124698918142227577300459309880&
                &4547151796062998955075830758511951858579711731676769660579988993526318854177162953020146688023840758&
                &4603622660648014297759540713505037980864913015716402406031178690879637251033587351277479527574859541&
                &7572920936651398752709055215663939505589207804914540432978557623565645991208599669097180808881920063&
                &7227714312184890119222096790535459636284173260024397328029395243137866685140273814343210366365711716&
                &7042358647275956123197079396783927914728272019537706060212263845788320480934171752680963925353944773&
                &0280863675704796054050525162959099932535265586464682793821550087166946662209865086040990507131145474&
                &2674110428395423227629949387596131127438371928396826762575553883728144908453957471281620658715882191&
                &0888724011665136196205080002917629993882608241754751673226993047313326125892184551681523545535431045&
                &8114528303607394526100730578774092094736822286015459361126642549541799645333882549670764145955017051&
                &3308000612538651401801532119293614565003435147928902055320217600618822326157365533772949809740595905&
                &2018796145979938674151302850593441045360348019238334932111517181105100410859283099181138255290906487&
                &3029533418691087118107895004426881765865961841419267486232005929789956207494587649901662172318722999&
                &4845123258260870315619363836897406865052797752967893316136838227985970406516005241290251498948731531&
                &9694209505667084746692764481259650670012944357951247923062137397808873125708979962290218382410541293&
                &0483065603459863120371744282301377070153823878609951218937542956964157950988060608985782910656238116&
                &1422035741047574518281708048752574462041283485138290827317223641893804935883389476643706232798207558&
                &3164620541748839306283820178954721954319445090211369992596537690819279215212221282457887933650687528&
                &8617303469517112245451315447164280392523574962804175375927948971096983905242318797695347043690474223&
                &8132665056397611644388442665313646268512196339944341540985621273959361844218214442734315345078601616&
                &1428702272098406156966033337278824103713153807737748015267058325792053556997331818811268567331899796&
                &7497786786001251403873023920127717626858627038170562807276699687356274072773403132694104831615879354&
                &3958115858251128378415632227616233344591881315378823557324830300859768903829697344762145934281912127&
                &1714133304757786755221851743106484876037319629031012446614508707837714052853304868420427879959665251&
                &4009368964527494988719996088230065668196236298805733689960371306226158464997243490564472254071897564&
                &1441285398399860960455632647712855850663041779957201017448443871583297673755604162078008788300720724&
                &1390865785566723954636935777578134428819598917631335685641784543423281488674422674670706697975557712&
                &1788798468777700116472954103621810567107869855646414713502627836321256957407217461738363552424248762&
                &4364780853518109957492932381740813319050481446127009055414257022203025376114948242287653245779337785&
                &1981877869734028258091278067497905893806255685600107605770598216668682475603756961576049761981948205&
                &2758118532729333127733603742149847001463931981340719681330844408263017545241644293372483217234561694&
                &2639378557592944486629790954192274518015884259778696940266014279196551684158959230431151917518727133&
                &4609575263460825447598815416225495259785319903964588374219923638761039583094807436598839770784963225&
                &2080920941206268114832425403540515474312327876180802357701527842702008781378306569508588571830140611&
                &0980426830095308627974030153554643774062498539644810004022317716657008936075218040845236685686491032&
                &5886266629337247244143556352059546170104239050079561583450594483732665254246744436486149918427509748&
                &5253621979537504128523848241127715641240965261646703516395599407360083455079665191393229410544185167&
                &9990997876554244625589008743884056491694537267393122602348155432978423086460721901479480729284567258&
                &3503954612118213364077776992584180757905173583882311275962271406750966991364528828189455892561297242&
                &5252452248453502562347348900936766966136332741088135837550717443838484760651019872222926016920811114&
                &6169371432077434885046020127763642567468723152059526010722289706864609324352227544963417635351891055&
                &48847634608972381760403137363968e4932_16
  logical, parameter :: test_ahuge2 = ahuge2 == zahuge2 .and. ahuge2 == dahuge2
  logical, parameter :: test_ahuge3 = ahuge3 == zahuge3 .and. ahuge3 == dahuge3
  logical, parameter :: test_ahuge4 = ahuge4 == zahuge4 .and. ahuge4 == dahuge4
  logical, parameter :: test_ahuge8 = ahuge8 == zahuge8 .and. ahuge8 == dahuge8
  logical, parameter :: test_ahuge10 = ahuge10 == zahuge10 .and. ahuge10 == dahuge10
  logical, parameter :: test_ahuge16 = ahuge16 == zahuge16 .and. ahuge16 == dahuge16

  real(2), parameter :: tiny2 = tiny(0._2), ztiny2 = real(z'0400', kind=2)
  real(3), parameter :: tiny3 = tiny(0._3), ztiny3 = real(z'0080', kind=3)
  real(4), parameter :: tiny4 = tiny(0._4), ztiny4 = real(z'00800000', kind=4)
  real(8), parameter :: tiny8 = tiny(0._8), ztiny8 = real(z'0010000000000000', kind=8)
  real(10), parameter :: tiny10 = tiny(0._10), ztiny10 = real(z'00018000000000000000', kind=10)
  real(16), parameter :: tiny16 = tiny(0._16), ztiny16 = real(z'00010000000000000000000000000000', kind=16)
  logical, parameter :: test_tiny2 = tiny2 == ztiny2
  logical, parameter :: test_tiny3 = tiny3 == ztiny3
  logical, parameter :: test_tiny4 = tiny4 == ztiny4
  logical, parameter :: test_tiny8 = tiny8 == ztiny8
  logical, parameter :: test_tiny10 = tiny10 == ztiny10
  logical, parameter :: test_tiny16 = tiny16 == ztiny16

  real,    parameter :: nan = real(z'7fc12345')
  integer, parameter :: nanInt = int(z'7fc12345')
  real,    parameter :: inf = real(z'7f800000')
  logical, parameter :: test_exponent_0 = exponent(0.0) == 0
  logical, parameter :: test_fraction_0 = fraction(0.) == 0.
  logical, parameter :: test_exponent_r8 = exponent(0.125) == -2
  logical, parameter :: test_fraction_r8 = fraction(0.125) == 0.5
  logical, parameter :: test_exponent_r4 = exponent(0.25) == -1
  logical, parameter :: test_fraction_mr4 = fraction(-0.25) == -0.5
  logical, parameter :: test_exponent_r2 = exponent(0.5) == 0
  logical, parameter :: test_fraction_r2 = fraction(0.5) == 0.5
  logical, parameter :: test_exponent_1 = exponent(1.0) == 1
  logical, parameter :: test_fraction_1 = fraction(1.) == 0.5
  logical, parameter :: test_exponent_4 = exponent(4.1) == 3
  logical, parameter :: test_fraction_m4 = fraction(-4.5) == -0.5625
  logical, parameter :: test_exponent_12 = exponent(12.9) == 4
  real,    parameter :: fraction_inf = fraction(inf)
  logical, parameter :: test_fraction_inf = fraction_inf /= fraction_inf ! must be NaN
  logical, parameter :: test_fraction_nan = transfer(fraction(nan),0) == nanInt

  integer, parameter :: &
    max2 = maxexponent(0._2), &
    max3 = maxexponent(0._3), &
    max4 = maxexponent(0._4), &
    max8 = maxexponent(0._8), &
    max10 = maxexponent(0._10), &
    max16 = maxexponent(0._16)
  logical, parameter :: test_max2 = max2 == 16
  logical, parameter :: test_max3 = max3 == 128
  logical, parameter :: test_max4 = max4 == 128
  logical, parameter :: test_max8 = max8 == 1024
  logical, parameter :: test_max10 = max10 == 16384
  logical, parameter :: test_max16 = max16 == 16384

  integer, parameter :: &
    min2 = minexponent(0._2), &
    min3 = minexponent(0._3), &
    min4 = minexponent(0._4), &
    min8 = minexponent(0._8), &
    min10 = minexponent(0._10), &
    min16 = minexponent(0._16)
  logical, parameter :: test_min2 = min2 == -13
  logical, parameter :: test_min3 = min3 == -125
  logical, parameter :: test_min4 = min4 == -125
  logical, parameter :: test_min8 = min8 == -1021
  logical, parameter :: test_min10 = min10 == -16381
  logical, parameter :: test_min16 = min16 == -16381

  integer, parameter :: &
    irange1 = range(0_1), &
    irange2 = range(0_2), &
    irange4 = range(0_4), &
    irange8 = range(0_8), &
    irange16 = range(0_16)
  logical, parameter :: test_irange1 = irange1 == 2
  logical, parameter :: test_irange2 = irange2 == 4
  logical, parameter :: test_irange4 = irange4 == 9
  logical, parameter :: test_irange8 = irange8 == 18
  logical, parameter :: test_irange16 = irange16 == 38

  integer, parameter :: &
    arange2 = range(0._2), zrange2 = range((0._2,0._2)), &
    arange3 = range(0._3), zrange3 = range((0._3, 0._3)), &
    arange4 = range(0._4), zrange4 = range((0._4, 0._4)), &
    arange8 = range(0._8), zrange8 = range((0._8, 0._8)), &
    arange10 = range(0._10), zrange10 = range((0._10, 0._10)), &
    arange16 = range(0._16), zrange16 = range((0._16, 0._16))
  logical, parameter :: test_arange2 = arange2 == 4 .and. zrange2 == 4
  logical, parameter :: test_arange3 = arange3 == 37 .and. zrange3 == 37
  logical, parameter :: test_zrange4 = arange4 == 37 .and. zrange4 == 37
  logical, parameter :: test_zrange8 = arange8 == 307 .and. zrange8 == 307
  logical, parameter :: test_zrange10 = arange10 == 4931 .and. zrange10 == 4931
  logical, parameter :: test_zrange16 = arange16 == 4931 .and. zrange16 == 4931

  logical, parameter :: test_set_exponent_z = set_exponent(0., 999) == 0.
  logical, parameter :: test_set_exponent_nan = transfer(set_exponent(nan, 0), 0) == nanInt
  real,    parameter :: set_expo_inf = set_exponent(inf, 0)
  integer, parameter :: set_expo_inf_int = transfer(set_expo_inf, 0)
  logical, parameter :: test_set_exponent_inf = shiftr(set_expo_inf_int, 23) == 255 .and. &
                                                shiftl(set_expo_inf_int, 9) /= 0 ! NaN
  logical, parameter :: test_set_exponent_0 = set_exponent(1., 0) == 0.5
  logical, parameter :: test_set_exponent_1 = set_exponent(1., 1) == 1.
  logical, parameter :: test_set_exponent_2 = set_exponent(1., 2) == 2.

end module
